﻿(function ($) {
    /**
     * 缓存名称
     * @type {string}
     * @private
     */
    var _cacheName = 'uiForm';
    /**
     * @class 表单组件
     * @constructor uiForm
     * @summary 构造函数
     * @param [options] {Object|String} 组件配置参数|要调用的组件方法名
     * @param [param] {Object} 表示要调用的方法的参数
     * @example
     * // 构件组件
     * $('#div').uiForm({
    *      axis:'h',
    *      onStopDrag: function(e){
    *          alert(this[0]==e.data.target[0]);
    *      }
    * });
     * // 调用组件方法options
     * $('#div').uiForm("options");
     */
    $.fn.uiForm = function (options, param) {
        if (typeof options == 'string') {
            return $.fn.uiForm.methods[options](this, param);
        }
        return this.each(function(){
            var me = $(this);
            options = options || {};
            if (!me.data(_cacheName)) {
                me.data(_cacheName,{
                    options: $.extend({}, $.fn.uiForm.defaults, options)
                });
                _setForm(me);
            }
        });
    };
    /**
     * 方法
     * @lends uiForm.prototype
     */
    $.fn.uiForm.methods = {
        /**
         * @summary 获得组件的数据对象
         * @name uiForm#data
         * @function
         * @returns {Array<Object>} 组件的数据对象
         */
        data: function (target) {
            try {
                return $.data(this[0], _cacheName);
            } catch (e) {
                return undefined;
            }
        },
        /**
         * @summary 提交组件的数据
         * @name uiForm#submit
         * @function
         * @param options {Object} 面板配置参数
         * @returns {jQuery} 方法调用者
         */
        submit: function (target, options) {
            var opts = $.extend({},
                $.fn.uiForm.defaults,
                $.data(target[0], _cacheName) ? $.data(target[0], _cacheName).options : {}, options || {}
            );
            _ajaxSubmit(target, opts);
            return target;
        },
        /**
         * @summary 为组件加载数据
         * @name uiForm#load
         * @function
         * @param data {Object} 数据
         * @returns {jQuery} 方法调用者
         */
        load: function (target, data) {
            _load(target, data);
            return target;
        },
        /**
         * @summary 清除组件的已选值
         * @name uiForm#clear
         * @function
         * @returns {jQuery} 组件对象
         */
        clear: function (target) {
            _clear(target);
            return target;
        },
        /**
         * @summary 重置组件的值
         * @name uiForm#reset
         * @function
         * @returns {jQuery} 组件对象
         */
        reset: function (target) {
            _reset(target);
            return target;
        },
        /**
         * @summary 验证组件的值
         * @name uiForm#validate
         * @function
         * @returns {jQuery} 组件对象
         */
        validate: function (target) {
            return _validate(target);
        },
        /**
         * @summary 禁止验证
         * @name uiForm#disableValidation
         * @function
         * @returns {jQuery} 组件对象
         */
        disableValidation: function (target) {
            _setValidation(target, true);
            return target;
        },
        /**
         * @summary 启用验证
         * @name uiForm#enableValidation
         * @function
         * @returns {jQuery} 组件对象
         */
        enableValidation: function (target) {
            _setValidation(this, false);
            return target;
        },
        /**
         * @summary 设置只读
         * @name uiForm#setReadonly
         * @function
         * @param readonly {Boolean} 是否只读
         * @returns {jQuery} 组件对象
         */
        setReadonly: function (target, readonly) {
            _setReadonly(target, readonly);
        }
    };
    /**
     * 默认配置
     * @lends uiForm.prototype
     */
    $.fn.uiForm.defaults = {
        /**
         * @type String
         * @default ""
         * @summary 指示组件的模板
         */
        template: '',
        /**
         * @type String
         * @default null
         * @summary 指定远程数据加载的url
         */
        url: null,
        /**
         * @summary 在对象提交时触发的方法。
         * @event
         * @name uiForm#onSubmit
         * @param param {Object} 参数
         * @this jQuery对象
         * @default emptyFn
         */
        onSubmit: function (param) {
            return $(this).uiForm('validate');
        },
        success: function (data) {
        },
        /**
         * @summary 在对象加载之前触发的方法。
         * @event
         * @name uiForm#onBeforeLoad
         * @param param {Object} 参数
         * @this jQuery对象
         * @default emptyFn
         */
        onBeforeLoad: function (param) {
        },
        /**
         * @summary 在对象加载成功时触发的方法。
         * @event
         * @name uiForm#onLoadSuccess
         * @param data {Object} 数据
         * @default emptyFn
         */
        onLoadSuccess: function (result) {
            if (result.success == undefined) {
            } else {
                if (!result.success) {
                    alert(result.message);
                }
            }
        },
        /**
         * @summary 在对象加载失败时触发的方法。
         * @event
         * @name uiForm#onLoadError
         * @default emptyFn
         */
        onLoadError: function () {
        },
        /**
         * @summary 在模板编译前触发的方法。
         * @event
         * @name uiForm#onBeforeCompile
         * @default emptyFn
         */
        onBeforeCompile: function (data) {

        }
    };
    var _setForm = function (target) {
        var options = $.data(target[0], _cacheName).options;
        target.setElemID();
        if (options.template != "") {
            var temp = $('#' + options.template);
            options.formTemp = temp.html();
            temp.remove();
        } else {

        }
        target.unbind('.uiForm').bind('submit.uiForm', function () {
            setTimeout(function () {
                _ajaxSubmit(target, options);
            }, 0);
            return false;
        });
    };
    var _ajaxSubmit = function (target, options) {
        options = options || {};
        var param = {ajax:true};
        if (options.onSubmit) {
            if (options.onSubmit.call(target, param) == false) {
                return;
            }
        }
        if (options.url) {
            target.attr('action', options.url);
        }
        var frameId = $.getIDByParentID(target.getElemID(), $.uiTemplate.uiForm.iframe);
        var frame = $('<iframe id=' + frameId + ' name=' + frameId + '></iframe>')
            .attr('src', window.ActiveXObject ? 'javascript:false' : 'about:blank')
            .css({
                position: 'absolute',
                top: -1000,
                left: -1000
            });
        var targetUrl = target.attr('target'), targetAction = target.attr('action');
        target.attr('target', frameId);

        var paramFields = $();
        try {
            frame.appendTo('body');
            frame.bind('load', cb);
            for (var n in param) {
                var f = $('<input type="hidden" name="' + n + '">').val(param[n]).appendTo(target);
                paramFields = paramFields.add(f);
            }
            checkState();
            target[0].submit();
        } finally {
            target.attr('action', targetAction);
            targetUrl ? target.attr('target', targetUrl) : target.removeAttr('target');
            paramFields.remove();
        }

        function checkState() {
            var f = $('#' + frameId);
            if (!f.length) {
                return
            }
            try {
                var s = f.contents()[0].readyState;
                if (s && s.toLowerCase() == 'uninitialized') {
                    setTimeout(checkState, 100);
                }
            } catch (e) {
                cb();
            }
        }

        var checkCount = 10;

        function cb() {
            var frame = $('#' + frameId);
            if (!frame.length) {
                return
            }
            frame.unbind();
            var data = '';
            try {
                var body = frame.contents().find('body');
                data = body.html();
                if (data == '') {
                    if (--checkCount) {
                        setTimeout(cb, 100);
                        return;
                    }
                }
                var ta = body.find('>textarea');
                if (ta.length) {
                    data = ta.val();
                } else {
                    var pre = body.find('>pre');
                    if (pre.length) {
                        data = pre.html();
                    }
                }
            } catch (e) {

            }
            if (options.success) {
                try {
                    data = JSON.parse(data);
                } catch (e) {
                }
                options.success(data);
            }
            setTimeout(function () {
                frame.unbind();
                try {
                    frame.contentWindow.document.write('');
                    frame.contentWindow.close();
                } catch (e) {
                }
                frame.remove();
                if (_IE) {
                    CollectGarbage();
                }
                frame = null;
            }, 100);
        }
    }

    var _load = function (target, data) {
        if (!$.data(target[0], _cacheName)) {
            $.data(target[0], _cacheName, {
                options: $.extend({}, $.fn.uiForm.defaults)
            });
        }
        var opts = $.data(target[0], _cacheName).options;

        if (typeof data == 'string') {
            var param = {};
            if (opts.onBeforeLoad.call(target, param) == false) return;

            $.ajax({
                url: data,
                data: param,
                showAlert:false,
                dataType: 'json',
                success: function (result) {
                    _loadTemp(result);
                },
                error: function () {
                    opts.onLoadError.apply(target, arguments);
                }
            });
        } else {
            _loadTemp(data);
        }

        function _loadTemp(result) {
            var data = result;
            if (data && result.data) {
                data = result.data || {};
            } else {
                data = data || {};
            }
            if(opts.onBeforeCompile.call(target, result)==false){
                return;
            }
            if (opts.template != "") {
                target.html(template.compile(opts.formTemp)(data));
            }
            opts.onLoadSuccess.call(target, result);
            _validate(target);
        }
    }

    var _clear = function (target) {
        $('input,select,textarea', target).each(function () {
            var t = this.type, tag = this.tagName.toLowerCase();
            if (t == 'text' || t == 'hidden' || t == 'password' || tag == 'textarea') {
                if (!$(this).hasClass('ui_validate_disabled')) {
                    this.value = '';
                }
            } else if (t == 'file') {
                var file = $(this);
                var newfile = file.clone().val('');
                newfile.insertAfter(file);
                if (file.data('uiValidate')) {
                    file.uiValidate('destroy');
                    newfile.uiValidate();
                } else {
                    file.remove();
                }
            } else if (t == 'checkbox' || t == 'radio') {
                this.checked = false;
            } else if (tag == 'select') {
                this.selectedIndex = -1;
            }

        });

        var t = $(target);
        var plugins = ['ui_combo'];
        for (var i = 0; i < plugins.length; i++) {
            var plugin = plugins[i];
            var r = t.find('.' + plugin + 'Origin');
            if (r.length && r[plugin]) {
                r[plugin]('clear');
            }
        }
        _validate(target);
    }

    var _reset = function (target) {
        target[0].reset();
        var plugins = ['ui_combo'];
        for (var i = 0; i < plugins.length; i++) {
            var plugin = plugins[i];
            var r = target.find('.' + plugin + 'Origin');
            if (r.length && r[plugin]) {
                r[plugin]('reset');
            }
        }
        _validate(target);
    }

    var _validate = function (target, objList) {
        if (objList == undefined) {
            objList = target.find('.ui_validate:not(:disabled)');
        }
        objList.each(function (index) {
            var ele = $(this);
            if ($.trim(ele.val()) == '') {
                ele.val('');
            }
            try {
                ele.uiValidate('validate');
            } catch (e) {
                ele.uiValidate();
            }
        });
        var invalidbox = target.find('.ui_validate-invalid');
        if (invalidbox.length > 0) {
            $(invalidbox[0]).focus();
            return false;
        }
        return true;
    }

    var _setValidation = function (target, novalidate) {
        target.find('.ui_validate:not(:disabled)').each(function () {
            $(this).uiValidate(novalidate ? 'disableValidation' : 'enableValidation');
        });
    }
    var _setReadonly = function (target, readonly) {
        target.find('.ui_validate').each(function () {
            var obj = $(this);
            $(this).uiValidate('setReadonly', readonly);
            if (this.tagName == 'TEXTAREA') {
                obj.addClass('ui_validate_disabled_tt');
            } else {
                obj.removeClass('ui_validate_disabled_tt');
            }
            removeStar(readonly);
        });
        target.find('.ui_comboOrigin').each(function () {
            $(this).uiCombo('setReadonly', readonly);
        });
        target.find('.ui_date').each(function () {
            $(this).uiDate('setReadonly', readonly);
        });
        target.find('.ui_ueditor').each(function () {
            $(this).uiUEditor('setReadonly', readonly);
        });

        function removeStar(t,readonly) {
            if(readonly){
                var starId=t.attr('id')+'-star';
                $('#'+starId).remove();
            }
        }
    }
})(jQuery);
